from collections import defaultdict
from location import Estate
from model import Position

class GameMap:
    def __init__(self,manager,mapFileName):
        self.manager=manager
        self._map=[line.strip('\n') for line in open(mapFileName).readlines()]
        
        self._dict={}
        self.location=defaultdict(lambda : defaultdict(lambda :(-1,-1)))
        self.streets=[]

        for (code,row) in enumerate(self._map):
            res=row.find(self.manager.config.startChar)
            if res==-1:
                continue

            startPos=(code,res)
            break

        self.loadMap(startPos)

    def loadMap(self,startPos):
        dirs=(
                (0,1),
                (1,0),
                (0,-1),
                (-1,0),
            )

        nowX,nowY=startPos
        now=0

        visited=defaultdict(lambda : defaultdict(lambda : False))
        lastLoc=False

        while not visited[nowX][nowY]:
            self[now]=self.parse(self._map[nowX][nowY],now)
            self.location[nowX][nowY]=now

            nowLoc=isinstance(self[now],Estate)
            st=len(self.streets)-1

            if lastLoc and nowLoc:
                self[now].street=st
                self.streets[st].append(self[now])

            elif nowLoc:
                self[now].street=st+1
                self.streets.append([self[now]])

            lastLoc=nowLoc

            visited[nowX][nowY]=True
            now+=1

            for dir_ in dirs:
                newX,newY=nowX+dir_[0],nowY+dir_[1]
                if not (0<=newX<len(self._map)) or not (0<=newY<len(self._map[newX])):
                    continue

                if self._map[newX][newY]==' ':
                    continue

                if not visited[newX][newY]:
                    nowX,nowY=newX,newY
                    break

        self.maxN=now

    def parse(self,char,pos):
        return self.manager.config.mapChar[char](self.manager,pos)

    def showOrignal(self):
        for row in self._map:
            self.manager.game.showText(row)

    def show(self,player):
        for row in range(len(self._map)):
            text=''

            for col in range(len(self._map[row])):
                loc=self.location[row].get(col,None)
                text+=self.encode(loc,player)

            self.manager.game.showText(text)

    def encode(self,location,player):
        if location is None:
            return ' '

        for p in self.manager.game.players:
            if location==p.pos:
                return str(p.code)

        location=self[location]
        return self.manager.config.charMap[location.name(player)]

    def __setitem__(self,key,value):
        if isinstance(key,Position):
            key=key.value

        self._dict[key]=value

    def __getitem__(self,key):
        if isinstance(key,Position):
            key=key.value

        return self._dict[key]
